package com.db.common.aspect;

import java.lang.reflect.Method;
import java.util.Date;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.db.common.annotation.RequiredLog;
import com.db.pojo.SysLog;
import com.db.service.SysLogService;
import com.db.utils.IPUtils;
import com.db.utils.ShiroUtils;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.extern.slf4j.Slf4j;




@Component
@Aspect
@Slf4j
public class SysLogAspect {

	@Pointcut("@annotation(com.db.common.annotation.RequiredLog)")
	public void logPointCut() {}
	@Around("logPointCut()")
	public Object around(ProceedingJoinPoint jp)
	throws Throwable{
		long t1=System.currentTimeMillis();
		log.info("start time:"+t1);
		Object result=jp.proceed();
		long t2=System.currentTimeMillis();
		log.info("end time:"+t2);
		saveLog(jp,(t2-t1));
		return result;
	}
	
	@Autowired
	private SysLogService sysLogService;
	
	private void saveLog(ProceedingJoinPoint jp,long time) throws Exception {
		 Method targetMethod=getTargetMethod(jp);
		 String classMethodName=getTargetMethodName(targetMethod);
		 String operation=getOperation(targetMethod);
		 String params=new ObjectMapper().writeValueAsString(jp.getArgs());
		 SysLog sysLog=new SysLog(null, 
				 ShiroUtils.getUsername(), 
				 operation, 
				 classMethodName, 
				 params, 
				 time, 
				 IPUtils.getIpAddr(), 
				 new Date());
		 sysLogService.saveObject(sysLog);
	}
	
	private String getOperation(Method targetMethod) {
		RequiredLog rLog=targetMethod.getAnnotation(RequiredLog.class);
		return rLog.value();
	}
	
	private String getTargetMethodName(Method targetMethod) {
		return targetMethod.getDeclaringClass().getName()
				+"."+targetMethod.getName();
	}
	
	private Method getTargetMethod(ProceedingJoinPoint jp) throws  Exception {
		Class<?> targetClass=jp.getTarget().getClass();
		MethodSignature s=(MethodSignature) jp.getSignature();
		Method targetMethod=targetClass.getMethod(
				s.getName(), s.getParameterTypes());
		return targetMethod;
				
	}
	
}
